﻿using System;
using System.IO;
using System.Net;
using System.Windows.Forms;

namespace MP2
{
    class File_Downloader
    {
        public string SSLocation;
        public string DMILocation;

        /// <summary>
        /// Checks the ABGX360 site for links for our active ISO in the program.
        /// </summary>
        /// <param name="XEX_CRC">Given XEX CRC32 for the dropped ISO</param>
        /// <returns>String array with links for SS/DMI files, or null if none are found</returns>
        /// <TODO> Refactor this whole method for speed and precision.</TODO>
        public string[] CheckForSSFiles(string XEX_CRC)
        {
            //Check that there's a valid CRC passed to the program.
            if (String.IsNullOrEmpty(XEX_CRC)) { return null; }
            if (XEX_CRC == "00000000") { return null; }

            try
            {
                HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create("http://www.abgx360.net/verified.php?f=pressings&q="+XEX_CRC);
                webRequest.Referer = "http://www.abgx360.net/verified.php";
                webRequest.UserAgent = "Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; SLCC1; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET CLR 1.1.4322)";
                webRequest.Timeout = 4500;

                HttpWebResponse response = (HttpWebResponse)webRequest.GetResponse();
                Stream responseStream = response.GetResponseStream();

                StreamReader reader = new StreamReader(response.GetResponseStream());
                string HTML_Line = null;

                //Store the URIs in here.
                string[] SS_DMI_LINKS = new string[2];

                while (responseStream != null)
                {
                    HTML_Line = reader.ReadLine();

                    //Will fix a bug that I've seen twice, where there was no overall 'else' option.
                    if (HTML_Line == null) { return null; }

                    //If the next line is SSv2, let's get that.
                    if (HTML_Line.IndexOf("<td class=rf>2</td>", 0, HTML_Line.Length) != -1)
                    {
                        int whereStart = HTML_Line.IndexOf("/Apps/StealthFiles/SS", 0, HTML_Line.Length);
                        string SSLink = HTML_Line.Substring(whereStart, 34);
                        SS_DMI_LINKS[0] = SSLink;

                        int whereStart2 = HTML_Line.IndexOf("/Apps/StealthFiles/DMI", 0, HTML_Line.Length);
                        string DMILink = HTML_Line.Substring(whereStart2, 35);
                        SS_DMI_LINKS[1] = DMILink;

                        return SS_DMI_LINKS;
                    }

                    //No SSv2. But there's SSv1. Ask if that's okay.
                    if (HTML_Line.IndexOf(">1</td>", 0, HTML_Line.Length) != -1)
                    {
                        /* Check to see if the user doesn't mind having SSv1.
                         * If they don't, go ahead and get the SSv1 files.
                         * Otherwise, don't get anything and return null.
                         */
                        var dialogSSv1 = MessageBox.Show("No SSv2 available for this game.\nBut I have found a valid SSv1.\n\nIs this okay?",
                            "Mousepatcher 2.0", MessageBoxButtons.YesNo, MessageBoxIcon.Question);

                        if (dialogSSv1 == DialogResult.Yes)
                        {
                            int whereStart = HTML_Line.IndexOf("/Apps/StealthFiles/SS", 0, HTML_Line.Length);
                            string SSLink = HTML_Line.Substring(whereStart, 34);
                            SS_DMI_LINKS[0] = SSLink;

                            int whereStart2 = HTML_Line.IndexOf("/Apps/StealthFiles/DMI", 0, HTML_Line.Length);
                            string DMILink = HTML_Line.Substring(whereStart2, 35);
                            SS_DMI_LINKS[1] = DMILink;

                            return SS_DMI_LINKS;
                        }

                        if ((dialogSSv1 == DialogResult.No) || (dialogSSv1 == DialogResult.None))
                        { return null; }
                    }

                    //There's no results. Tell the user and quit operation.
                    // Occasionally, getting this means you've got a bug in the code. - Matt_Ryder
                    if (HTML_Line == "<p>No results were found</p>\t\t</div>")
                    {
                        //No SSv1 or SSv2 available, tell user.
                        MessageBox.Show("No SSv1 or SSv2 available for this game.", "Mousepatcher 2.0");
                        return null;
                    }
                }

                responseStream.Dispose();
                return null;
            }

            catch (System.Exception ex)
            {MessageBox.Show("EXCEPTION @:"+ex.TargetSite+"\nMESSAGE:"+ex.Message, "Mousepatcher 2.0"); return null; }
        }

        /// <summary>
        /// Physically downloads the SS from the servers to the disk.
        /// </summary>
        /// <param name="XEXCRC">CRC32 given to the method identifying the ISO</param>
        public bool DownloadSSFiles(string XEXCRC)
        {
            //Check there's files to download, by calling GetLinks to scan ABGX360 for some.
            string[] DownloadLinks = CheckForSSFiles(XEXCRC);

            //Check there's files to download.
            if (DownloadLinks == null) { return false; }
            if (DownloadLinks.Length < 2) { return false; }

            try
            {
                string mpDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\Mousepatcher2.0");
                if (!Directory.Exists(mpDir))
                { Directory.CreateDirectory(mpDir); }

                Uri SS_URI = new Uri("http://www.abgx360.net" + DownloadLinks[0]);
                Uri DMI_URI = new Uri("http://www.abgx360.net" + DownloadLinks[1]);

                //Download SS file to file.
                DownloadFilesFromURI(SS_URI);

                //Download DMI file to file.
                DownloadFilesFromURI(DMI_URI);

                return true;
            }
            catch (System.Exception ex)
            { MessageBox.Show("EXCEPTION @:" + ex.TargetSite + "\nMESSAGE:" + ex.Message, "Mousepatcher 2.0"); return false; }
        }

        /// <summary>
        /// Downloads a file from a specified URI
        /// </summary>
        /// <param name="SSURI">The URI for the SS File</param>
        private void DownloadFilesFromURI(Uri SSURI)
        {
            if (String.IsNullOrEmpty(SSURI.OriginalString)) { throw new Exception(); }
            try
            {
                FileStream DataFilestream;
                string mpDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\Mousepatcher2.0");
                byte[] buffer = new byte[2048];

                //Get the file from the URI.
                HttpWebRequest DataRequest = (HttpWebRequest)WebRequest.Create(SSURI);
                HttpWebResponse DataResponse = (HttpWebResponse)DataRequest.GetResponse();

                BinaryReader DataReader = new BinaryReader(DataResponse.GetResponseStream());
                DataReader.Read(buffer, 0, 2048);

                string DataFileName = DataResponse.ResponseUri.Segments[DataResponse.ResponseUri.Segments.Length - 1];
                //Name file from uri reponse.
                if (DataFileName.IndexOf("SS", 0, DataFileName.Length) != -1)
                {
                    SSLocation = mpDir + "\\" + DataFileName;
                    DataFilestream = new FileStream(SSLocation, FileMode.Create);
                    DataFilestream.Write(buffer, 0, 2048);
                    DataFilestream.Close();
                }

                else if (DataFileName.IndexOf("DMI", 0, DataFileName.Length) != -1)
                {
                    DMILocation = mpDir + "\\" + DataFileName;
                    DataFilestream = new FileStream(DMILocation, FileMode.Create);
                    DataFilestream.Write(buffer, 0, 2048);
                    DataFilestream.Close();
                }
            }
            catch (System.Exception ex)
            { MessageBox.Show("EXCEPTION @:" + ex.TargetSite + "\nMESSAGE:" + ex.Message, "Mousepatcher 2.0"); }
        }
    }
}
